Completed
Push — master ( b362d9...2b4a65 )
by Sander
50s
created

$j.ready   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 6
rs 9.4285
c 1
b 1
f 0
1
/* global API */
2
var $j = jQuery.noConflict();
3
4
$j(document).ready(function () {
5
    var _this = this;
6
    Array.prototype.findUrl = function (match) {
0 ignored issues
show
Compatibility Best Practice introduced by
You are extending the built-in type Array. This may have unintended consequences on other objects using this built-in type. Consider subclassing instead.
Loading history...
7
        return this.filter(function (item) {
8
            return typeof item === 'string' && item.indexOf(match) > -1;
9
        });
10
    };
11
12
    function removePasswordPicker() {
13
        $j('.passwordPickerIframe').remove();
14
    }
15
16
    _this.removePasswordPicker = removePasswordPicker;
17
18
    function enterLoginDetails(login) {
19
        var username;
20
21
        if (login.hasOwnProperty('username')) {
22
            username = (login.username.trim() !== '' ) ? login.username : login.email;
23
        }
24
25
        fillPassword(username, login.password);
0 ignored issues
show
Bug introduced by
The variable username does not seem to be initialized in case login.hasOwnProperty("username") on line 21 is false. Are you sure the function fillPassword handles undefined variables?
Loading history...
26
        if ($j('.passwordPickerIframe').is(':visible')) {
27
            removePasswordPicker();
28
        }
29
    }
30
31
    _this.enterLoginDetails = enterLoginDetails;
32
33
34
    function showPasswordPicker(form) {
35
        if ($j('.passwordPickerIframe').length > 1) {
36
            return;
37
        }
38
        var loginField = $j(form[0]);
39
        var loginFieldPos = loginField.offset();
40
        var position = $j(form[1]).position();
0 ignored issues
show
Unused Code introduced by
The assignment to variable position seems to be never used. Consider removing it.
Loading history...
41
        var passwordField = $j(form[1]);
42
        var passwordFieldPos = passwordField.offset();
43
44
        var left = (loginFieldPos) ? loginFieldPos.left : passwordFieldPos.left;
45
        var top = (loginFieldPos) ? loginFieldPos.top : passwordFieldPos.top;
46
        var maxZ = Math.max.apply(null,
47
            $j.map($j('body *'), function (e) {
48
                if ($j(e).css('position') !== 'static')
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $j(e).css("position") !== "static" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
49
                    return parseInt($j(e).css('z-index')) || 1;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
50
            }));
51
        if (loginFieldPos && passwordFieldPos.top > loginFieldPos.top) {
52
            //console.log('login fields below each other')
53
            top = passwordFieldPos.top + passwordField.height() + 10;
54
        } else {
55
            // console.log('login fields next to each other')
56
            if(loginFieldPos){
57
                top =  top + loginField.height() + 10;
58
            } else {
59
                top =  top + passwordField.height() + 10;
60
            }
61
        }
62
63
64
        var pickerUrl = API.extension.getURL('/html/inject/password_picker.html');
65
66
        var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="385" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>');
67
        picker.css('position', 'absolute');
68
        picker.css('left', left);
69
        picker.css('z-index', maxZ + 10);
70
        picker.css('top', top);
71
        $j('body').prepend($j(picker));
72
        // picker.css('width', $j(form).width());
73
        $j('.passwordPickerIframe:not(:last)').remove();
74
    }
75
76
    function createFormIcon(el, form) {
77
        var offset = el.offset();
0 ignored issues
show
Unused Code introduced by
The assignment to variable offset seems to be never used. Consider removing it.
Loading history...
78
        var width = el.width();
79
        var height = el.height() * 1;
80
        var margin = (el.css('margin')) ? parseInt(el.css('margin').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
81
        var padding = (el.css('padding')) ? parseInt(el.css('padding').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable padding seems to be never used. Consider removing it.
Loading history...
82
83
        var pickerIcon = API.extension.getURL('/icons/icon.svg');
84
        $j(el).css('background-image', 'url("' + pickerIcon + '")');
85
        $j(el).css('background-repeat', 'no-repeat');
86
        //$j(el).css('background-position', '');
87
        $j(el).css('cssText', el.attr('style')+' background-position: right 3px center !important;');
88
89
90
        function onClick(e) {
91
            e.preventDefault();
92
            var offsetX = e.offsetX;
93
            var offsetRight = (width - offsetX);
94
            if (offsetRight < height) {
95
                showPasswordPicker(form);
96
            }
97
        }
98
99
        // $j(el).bind('click', onClick);
100
        $j(el).click(onClick);
101
102
    }
103
104
    function createPasswordPicker(form) {
105
        for (var i = 0; i < form.length; i++) {
106
            var el = $j(form[i]);
107
            createFormIcon(el, form);
108
109
        }
110
    }
111
112
    function formSubmitted(fields) {
113
        var user = fields[0].value;
114
        var pass = fields[1].value;
115
        var params = {
116
            username: user,
117
            password: pass
118
        };
119
        //Disable password mining
120
        //$j(fields[1]).attr('type', 'hidden');
121
        API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params});
122
123
    }
124
125
    function inIframe() {
126
        try {
127
            return window.self !== window.top;
128
        } catch (e) {
129
            return true;
130
        }
131
    }
132
133
    function showDoorhanger(data) {
134
        if (inIframe()) {
135
            return;
136
        }
137
        data.data.currentLocation = window.location.href;
138
        API.runtime.sendMessage(API.runtime.id, {method: "setDoorhangerData", args: data});
139
        var pickerUrl = API.extension.getURL('/html/inject/doorhanger.html');
140
141
        var doorhanger = $j('<iframe id="password-toolbarIframe" style="display: none;" scrolling="no" height="80" width="100%" frameborder="0" src="' + pickerUrl + '"></iframe>');
142
        $j('#password-toolbarIframe').remove();
143
        $j('body').prepend(doorhanger);
144
        $j('#password-toolbarIframe').fadeIn();
145
    }
146
147
    _this.showDoorhanger = showDoorhanger;
148
149
    function showUrlUpdateDoorhanger(data) {
150
        var buttons = ['cancel', 'updateUrl'];
151
        showDoorhanger({
152
            data: data.data,
153
            buttons: buttons
154
        });
155
    }
156
157
    _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger;
158
159
    function checkForMined() {
160
        if (inIframe()) {
161
            return;
162
        }
163
164
        API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) {
165
            if (!data) {
166
                return;
167
            }
168
            if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) {
169
                var buttons = ['cancel', 'save', 'ignore'];
170
                showDoorhanger({data: data, buttons: buttons});
171
            }
172
        });
173
    }
174
175
176
    function closeDoorhanger() {
177
        $j('#password-toolbarIframe').slideUp(400, function () {
178
            $j('#password-toolbarIframe').remove();
179
        });
180
    }
181
182
    _this.closeDoorhanger = closeDoorhanger;
183
184
    function initForms() {
185
        API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (settings) {
186
            var disablePasswordPicker = settings.disablePasswordPicker;
187
            var url = window.location.href;
188
            var loginFields = getLoginFields();
189
            if (loginFields.length > 0) {
190
                for (var i = 0; i < loginFields.length; i++) {
191
                    var form = getFormFromElement(loginFields[i][0]);
192
                    if (!disablePasswordPicker) {
193
                        createPasswordPicker(loginFields[i], form);
0 ignored issues
show
Bug introduced by
The call to createPasswordPicker seems to have too many arguments starting with form.
Loading history...
194
                    }
195
196
                    if (settings.disable_browser_autofill) {
197
                        $j(form).attr('autocomplete', 'off');
198
                    }
199
200
                    //Password miner
201
                    /* jshint ignore:start */
202
                    if (!settings.hasOwnProperty('ignored_sites') || settings.ignored_sites.findUrl(url) !== -1) {
203
                        $j(form).submit((function (loginFields) {
204
                            return function () {
205
                                formSubmitted(loginFields);
206
                            };
207
                        })(loginFields[i]));
208
                    }
209
                    /* jshint ignore:end */
210
                }
211
212
                API.runtime.sendMessage(API.runtime.id, {
213
                    method: "getCredentialsByUrl",
214
                    args: url
215
                }).then(function (logins) {
216
                    console.log('Found ' + logins.length + ' logins for this site');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
217
                    if (logins.length === 1) {
218
                        API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) {
219
                            if (isEnabled) {
220
                                enterLoginDetails(logins[0]);
221
                            }
222
                        });
223
                    }
224
225
                });
226
            }
227
228
        });
229
    }
230
231
    function minedLoginSaved(args) {
232
        // If the login added by the user then this is true
233
        if (args.selfAdded) {
234
            enterLoginDetails(args.credential);
235
        }
236
    }
237
238
    _this.minedLoginSaved = minedLoginSaved;
239
240
    function copyText(text) {
241
        var txtToCopy = document.createElement('input');
242
        txtToCopy.style.left = '-300px';
243
        txtToCopy.style.position = 'absolute';
244
        txtToCopy.value = text;
245
        document.body.appendChild(txtToCopy);
246
        txtToCopy.select();
247
        document.execCommand('copy');
248
        txtToCopy.parentNode.removeChild(txtToCopy);
249
    }
250
251
    _this.copyText = copyText;
252
253
    function init() {
254
        checkForMined();
255
        initForms();
256
    }
257
258
    var readyStateCheckInterval = setInterval(function () {
259
        if (document.readyState === "complete") {
260
            clearInterval(readyStateCheckInterval);
261
            API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) {
262
                if (result) {
263
                    init();
264
                    var body = document.getElementsByTagName('body')[0];
0 ignored issues
show
Unused Code introduced by
The variable body seems to be never used. Consider removing it.
Loading history...
265
                    // observeDOM(body, function () {
266
                    //     initForms();
267
                    // });
268
                } else {
269
                    console.log('[Passman extension] Stopping, vault key not set');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
270
                }
271
            });
272
        }
273
    }, 10);
274
275
    API.runtime.onMessage.addListener(function (msg, sender) {
276
        //console.log('Method call', msg.method);
277
        if (_this[msg.method]) {
278
            _this[msg.method](msg.args, sender);
279
        }
280
    });
281
});
282